/*
 * @Author: MainStart pxclihai@126.com
 * @Date: 2024-07-24 15:19:34
 * @LastEditors: MainStart pxclihai@126.com
 * @LastEditTime: 2024-07-27 16:15:11
 * @FilePath: \edied:\wdjg\project\wzjgwkfty03_mcu\babyos\bos\drivers\b_drv_ec11.c
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置:
 * https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
/**
 *!
 * \file
 * \version
 * \date
 * \author
 *******************************************************************************
 * @attention
 */

/*Includes ----------------------------------------------*/
#include "drivers/inc/b_drv_ec11.h"

#include "b_os.h"
/**
 * \addtogroup B_DRIVER
 * \{
 */

/**
 * \addtogroup EC11
 * \{
 */

/**
 * \defgroup EC11_Private_TypesDefinitions
 * \{
 */

//----------------IO口定义----------------//
#define EC11_A_Now bMcuGpioReadPin(_if->aPin.port, _if->aPin.pin)  // EC11的A引脚，视为时钟线
#define EC11_B_Now bMcuGpioReadPin(_if->bPin.port, _if->bPin.pin)  // EC11的B引脚，视为信号线
//----------------编码器参数微调宏定义----------------//
#define EC11_SCAN_PERIOD_MS 2                                // EC11编码器扫描周期
#define KEY_COUNT_DESHAKING (20 / EC11_SCAN_PERIOD_MS)       // 按键消抖时间
#define KEY_COUNT_LONGTIME (600 / EC11_SCAN_PERIOD_MS)       // 长按按键判断时间
#define KEY_COUNT_DUALCLICKTIME (150 / EC11_SCAN_PERIOD_MS)  // 双击按键判断时间
#define KEY_LONG_REPEAT_TIME \
    (200 / EC11_SCAN_PERIOD_MS)  // 长按按键的回报率的倒数，即一直长按按键时响应的时间间隔

//----------------局部文件内变量列表----------------//
static char EC11_A_Last = 0;  // EC11的A引脚上一次的状态
static char EC11_B_Last = 0;  // EC11的B引脚上一次的状态
static char EC11_Type =
    1;  // 定义变量暂存EC11的类型---->>>>----  0：一定位对应一脉冲；  1：两定位对应一脉冲
        // 所谓一定位对应一脉冲，是指EC11旋转编码器每转动一格，A和B都会输出一个完整的方波。
        // 而
        // 两定位对应一脉冲，是指EC11旋转编码器每转动两格，A和B才会输出一个完整的方波，只转动一格只输出A和B的上升沿或下降沿
static bDriverInterface_t *_pdrv;
static drv_cb_t            _cb_handler;
/**
 * \}
 */

/**
 * \defgroup EC11_Private_Defines
 * \{
 */
#define DRIVER_NAME EC11
/**
 * \}
 */

/**
 * \defgroup EC11_Private_Macros
 * \{
 */

/**
 * \}
 */

/**
 * \defgroup EC11_Private_Variables
 * \{
 */
bDRIVER_HALIF_TABLE(bEC11_HalIf_t, DRIVER_NAME);
/**
 * \}
 */

/**
 * \defgroup EC11_Private_FunctionPrototypes
 * \{
 */

/**
 * \}
 */

/**
 * \defgroup EC11_Private_Functions
 * \{
 */

//*******************************************************************/
// 功能：扫描EC11旋转编码器的动作并将参数返回给动作分析函数使用
// 形参：EC11旋转编码器的类型-->>  unsigned char Set_EC11_TYPE  <<--
// ：0----一定位对应一脉冲；1（或非0）----两定位对应一脉冲 返回：EC11旋转编码器的扫描结果-->>  char
// ScanResult  -->>  0：无动作；1：正转； -1：反转；2：只按下按键；3：按着按键正转；-3：按着按键反转
// 详解：只扫描EC11旋转编码器有没有动作，不关心是第几次按下按键或长按或双击。返回值直接作为形参传给
// [ void Encoder_EC11_Analyze(char EC11_Value); ] 函数使用
//*******************************************************************/
static int Encoder_EC11_Scan(void)
{
    bDRIVER_GET_HALIF(_if, bEC11_HalIf_t, _pdrv);
    // 以下储存A、B上一次值的变量声明为静态全局变量，方便对EC11对应的IO口做初始化
    //   static char EC11_A_Last = 0;
    //   static char EC11_B_Last = 0;
    int ScanResult = 0;  // 返回编码器扫描结果，用于分析编码器的动作
                         // 返回值的取值：   0：无动作；      1：正转；           -1：反转；
                         //                   2：只按下按键；    3：按着按键正转； -3：按着按键反转
                         //======================================================//
    if (EC11_Type == 0)  //================一定位对应一脉冲的EC11================//
    {                    //======================================================//
        if (EC11_A_Now != EC11_A_Last)  // 以A为时钟，B为数据。正转时AB反相，反转时AB同相
        {
            if (EC11_A_Now == 0)
            {
                if (EC11_B_Now ==
                    1)  // 只需要采集A的上升沿或下降沿的任意一个状态，若A下降沿时B为1，正转
                    ScanResult = 1;  // 正转

                else  // 反转
                    ScanResult = -1;
            }
            EC11_A_Last = EC11_A_Now;  // 更新编码器上一个状态暂存变量
            EC11_B_Last = EC11_B_Now;  // 更新编码器上一个状态暂存变量
        }
    }
    //======================================================//
    else  //================两定位对应一脉冲的EC11================//
    {     //======================================================//
        if (EC11_A_Now !=
            EC11_A_Last)  // 当A发生跳变时采集B当前的状态，并将B与上一次的状态进行对比。
        {  // 若A 0->1 时，B 1->0 正转；若A 1->0 时，B 0->1 正转；
           // 若A 0->1 时，B 0->1 反转；若A 1->0 时，B 1->0 反转
            if (EC11_A_Now == 1)  // EC11_A和上一次状态相比，为上升沿
            {
                if ((EC11_B_Last == 1) && (EC11_B_Now == 0))  // EC11_B和上一次状态相比，为下降沿
                    ScanResult = 1;                           // 正转

                if ((EC11_B_Last == 0) && (EC11_B_Now == 1))  // EC11_B和上一次状态相比，为上升沿
                    ScanResult = -1;                          // 反转

                //>>>>>>>>>>>>>>>>下面为正转一次再反转或反转一次再正转处理<<<<<<<<<<<<<<<<//
                if ((EC11_B_Last == EC11_B_Now) &&
                    (EC11_B_Now == 0))  // A上升沿时，采集的B不变且为0
                    ScanResult = 1;     // 正转

                if ((EC11_B_Last == EC11_B_Now) &&
                    (EC11_B_Now == 1))  // A上升沿时，采集的B不变且为1
                    ScanResult = -1;    // 反转
            }

            else  // EC11_A和上一次状态相比，为下降沿
            {
                if ((EC11_B_Last == 1) && (EC11_B_Now == 0))  // EC11_B和上一次状态相比，为下降沿
                    ScanResult = -1;                          // 反转

                if ((EC11_B_Last == 0) && (EC11_B_Now == 1))  // EC11_B和上一次状态相比，为上升沿
                    ScanResult = 1;                           // 正转

                //>>>>>>>>>>>>>>>>下面为正转一次再反转或反转一次再正转处理<<<<<<<<<<<<<<<<//
                if ((EC11_B_Last == EC11_B_Now) &&
                    (EC11_B_Now == 0))  // A上升沿时，采集的B不变且为0
                    ScanResult = -1;    // 反转

                if ((EC11_B_Last == EC11_B_Now) &&
                    (EC11_B_Now == 1))  // A上升沿时，采集的B不变且为1
                    ScanResult = 1;     // 正转
            }
            EC11_A_Last = EC11_A_Now;  // 更新编码器上一个状态暂存变量
            EC11_B_Last = EC11_B_Now;  // 更新编码器上一个状态暂存变量
        }
    }

    return ScanResult;  // 返回值的取值：   0：无动作；      1：正转；           -1：反转；
}  //              2：只按下按键；    3：按着按键正转；   -3：按着按键反转
#include "b_os.h"
static int _bEC11Ctl(bDriverInterface_t *pdrv, uint8_t cmd, void *param)
{
    if (cmd == bCMD_EC11_REG_CALLBACK)
    {
        if (param != NULL)
        { 
            _cb_handler = (drv_cb_t *)param;
        }
    }
}
static int _bEc11Read(bDriverInterface_t *pdrv, uint32_t off, uint8_t *pbuf, uint32_t len)
{
    if (len == 0)
    {
        return -1;
    }
    bDRIVER_GET_HALIF(_if, bEC11_HalIf_t, pdrv);
    // pbuf[0] = (bHalGpioReadPin(_if->port, _if->pin) == _if->level);
    return 1;
}
static void _bEc11Core()
{
    static uint32_t tick = 0;
   // if (bHalGetSysTick() - tick > MS2TICKS(4))
    {
        tick          = bHalGetSysTick();
        int direction = Encoder_EC11_Scan();
        if (_cb_handler != NULL)
        {
            if (direction == 1)
            {
                _cb_handler(_pdrv->drv_no, &direction);
            }
            else if (direction == -1)
            {
                _cb_handler(_pdrv->drv_no, &direction);
            }
        }
    }
}

#ifdef BSECTION_NEED_PRAGMA
#pragma section bos_polling
#endif
BOS_REG_POLLING_FUNC(_bEc11Core);
#ifdef BSECTION_NEED_PRAGMA
#pragma section
#endif
/**
 * \}
 */

/**
 * \addtogroup EC11_Exported_Functions
 * \{
 */
#include "b_os.h"
int bEC11_Init(bDriverInterface_t *pdrv)
{
    bDRIVER_STRUCT_INIT(pdrv, DRIVER_NAME, bEC11_Init);
    bDRIVER_GET_HALIF(_if, bEC11_HalIf_t, pdrv);
    _pdrv      = pdrv;
    pdrv->read = _bEc11Read;
    pdrv->ctl  = _bEC11Ctl;
    // EC11类型选择：0-一定位一脉冲；1-两定位一脉冲
    if (_if->type == 0)
    {
        EC11_Type = 0;
    }
    else
    {
        EC11_Type = 1;
    }
    b_log("ec11 type %d \n", _if->type);
    // 避免上电时EC11旋钮位置不确定导致一次动作误判
    EC11_A_Last = EC11_A_Now;
    EC11_B_Last = EC11_B_Now;

    bMcuGpioConfig(_if->aPin.port, _if->aPin.pin, B_HAL_GPIO_INPUT, B_HAL_GPIO_PULLUP);
    bMcuGpioConfig(_if->bPin.port, _if->bPin.pin, B_HAL_GPIO_INPUT, B_HAL_GPIO_PULLUP);
    return 0;
}

#ifdef BSECTION_NEED_PRAGMA
#pragma section driver_init
#endif
bDRIVER_REG_INIT(B_DRIVER_EC11, bEC11_Init);
#ifdef BSECTION_NEED_PRAGMA
#pragma section
#endif
/**
 * \}
 */

/**
 * \}
 */

/**
 * \}
 */

/************************ Copyright (c) 2020 Bean *****END OF FILE****/
